#ifndef _COMM_HPP_
#define _COMM_HPP

#include<iostream>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<cerrno>
#include<cstring>
#include<cstdlib>
using namespace std;
using std::cout;
using std::endl;

#define PATHNAME "." //确定多个进程采用相同的路径
#define PROJ_ID 0x55 //确定多个进程采用相同的项目id（标识符）
#define MAX_SIZE 4096//共享内存块的大小，单位是字节

key_t GetKey()
{
    key_t k = ftok(PATHNAME,PROJ_ID);
    if(k < 0)
    {
        //cin,cout,cerr -> stdin,stdout,stderr -> 0,1,2
        //strerror将错误码转化为错误码的描述
        cerr << errno << ":" << strerror(errno) << endl;//像文件标识符2打印，也就是标准错误输出
        exit(1);
    }
    return k;
}

int get_shmflg(key_t k,int flag)
{
    int shmid = shmget(k,MAX_SIZE,flag);
    if(shmid < 0)
    {
        cerr << errno <<" : "<<strerror(errno)<<endl;
        exit(2);
    }
    return shmid;
}

int create_shm(key_t k)//创建共享内存块
{
    return get_shmflg(k,IPC_CREAT | IPC_EXCL | 0600);//这个0600是权限的意思，是ipsc -m中perms需要的
}

int get_shm(key_t k)//获取共享内存块
{
    return get_shmflg(k,IPC_CREAT);//这里也可以是0，0也表示获取。这就相当于if else if 和else，这里的0就是else，匹配获取
}

void delshm(int shmid)
{
    if(shmctl(shmid,IPC_RMID,nullptr) == -1);//删除失败
    {
        cerr << errno<<" : "<< strerror(errno) << endl;
    }
}

void* attchshm(int shmid)//挂接函数
{
    //纯数字没有任何意义，必须有类型才有意义
    //int a =10;编译器推导+隐式类型转换
    //100;字面值
    //10u 无符号整数
    //10L
    //10.0f
    //10
    void* mm = shmat(shmid,nullptr,0);//64位系统指针大小是8个字节，int是4个字节，精度丢失
    if((long long)mm < 0)
    {
        cerr << errno<<" : "<< strerror(errno) << endl;
        exit(3);
    }
    return mm;
}

void detachshm(void* start)
{
    if(shmdt(start) == -1)
    {
        cerr << errno<<" : "<< strerror(errno) << endl;
        exit(4);
    }
}

#endif